const CacheBlock = require('./CacheBlock')
const { env } = require('process')
const colors = require('colors')
const Protocol = require('./Protocol')

class State {
    /**
     * 
     * @param {CacheBlock} block 
     */
    constructor(block) {
        this.block = block
    }

    prRd() { }

    prWr() { }

    busRd() { }

    busRdX() { }

    flush() {
        if(this.block.content == -1)return
        Protocol.flush(this.block)
    }

    show(){}

    getMsg(){
        let msg = ''
        if(env.lang === 'en')msg = `processor ${this.block.processor}'s ${this.block.id} block's state has change to ${this.block.currentState.__proto__.constructor.name}`
        if(env.lang === 'zh')msg = `处理机 ${this.block.processor} 的 ${this.block.id} 号缓存块的状态变为 ${this.block.currentState.__proto__.constructor.name}`
        return msg
    }

    getName(){
        return this.block.currentState.__proto__.constructor.name + ` ${this.block.content}`
    }
}

class Invalid extends State {
    constructor(block) {
        super(block)
    }

    prRd() {
        Protocol.busRd(this.block)
        this.block.changeState('Shared')
    }

    prWr() {
        Protocol.busRdX(this.block)
        this.block.changeState('Modified')
    }

    show(){
        let msg = this.getMsg()
        console.log(colors.gray(msg))
    }

    getName(){
        return colors.gray(super.getName())
    }
}

class Modified extends State {
    constructor(block) {
        super(block)
    }

    busRd() {
        this.block.flush()
        this.block.changeState('Shared')
    }

    busRdX() {
        this.block.flush()
        this.block.changeContent(-1)
        this.block.changeState('Invalid')
    }

    show(){
        let msg = this.getMsg()
        console.log(colors.red(msg))
    }

    getName(){
        return colors.red(super.getName())
    }
}

class Shared extends State {
    constructor(block) {
        super(block)
    }

    prWr() {
        Protocol.busRdX(this.block)
        this.block.changeState('Modified')
    }

    busRdX() {
        this.block.changeContent(-1)
        this.block.changeState('Invalid')
    }

    show(){
        let msg = this.getMsg()
        console.log(colors.blue(msg))
    }

    getName(){
        return colors.blue(super.getName())
    }
}

exports.Invalid = Invalid
exports.Modified = Modified
exports.Shared = Shared